/*
    1,字符串处理函数
    $e  $extract    按位置截取字符串（从指定起止索引提取子串）     w $e("abcd",2,3) → "bc"
    $l  $length     返回字符串长度或分隔符子串数量                 w $l("a^b^c","^") → 3
    $f  $find       查找子串位置（返回子串结束位置+1，未找到返回0）w $f("hello","ll") → 4
    $tr $translate  字符替换（一对一映射替换）                     w $tr("abc","a","x") → "xbc"
    $re $replace    字符串替换（将指定子串替换为新串）             w $re("apple","p","x") → "axxle"

    2,变量与数据操作
    $g  $get    安全获取变量值（未定义时返回空或默认值）           s val=$g(^data(99),0) → 若 ^data(99) 未定义，返回 0
    $d  $data   检查变量状态（返回值含义：0-未定义，1-有值无子节点，10-有子节点无值，11-有值有子节点）    w $d(^user) → 11 17
    $o  $order  遍历数组/global 的下一个索引（常用于循环）         s idx=" f { s idx=$o(^data(idx)) q:idx=" } 1
    $l  $length 获取字符串长度或分隔符分段数2
    $g  $get    安全获取变量值（避免未定义错误）2
    $$$ 宏定义（如 $$$yes）   预定义常量（需包含 %occstatus.inc 等头文件）
    
    3,日期与时间函数
    $h   $horolog    返回当前日期时间（数字格式：日期从1840-12-31起算，时间从午夜起秒数） w $h → 65000,43200（表示2025-06-20 12:00:00）
    $zd  $zdate      格式化日期（将 $h 日期部分转为文本）          w $zd($h,"yyyy-mm-dd") → "2025-06-20"
    $zth $ztimeh     将时间文本转为 $h 格式的时间部分              s time=$zth("12:30:00") → 45000

    4,类型转换与格式化
    $j  $justify    右对齐并格式化数值（可指定宽度和小数位）       w $j(3.14,10,2) → " 3.14"
    $zc $zconvert   大小写/编码转换（如转大写/小写/utf8）          w $zc("abc","u") → "abc"
    例如: $ZCVT("ABC","L")  ;abc 统一转为小写便于比较
        "U" 转换为大写   "abc" → "ABC"
        "T" 首字母大写   "hello" → "Hello"
        "E" HTML/URL 编码 "A&B" → "A%26B"
        "D" HTML/URL 解码 "A%26B" → "A&B"

    5,命令简写
    set     s   变量赋值（可单变量或多变量）                       s x=1 或 s (a,b)="ok"
    write   w   输出内容到当前设备                                 w "hello",!（! 表示换行）
    kill    k   删除变量或清空 global 数据                         k x 或 k ^tmp
    quit    q   退出方法/函数（可带返回值）                        q 0（返回状态码 0）
    do      d   调用子程序或方法                                   d ##class(myclass).mymethod()
    merge   m   复制变量树（常用于备份 global 结构）               m ^backup=^original
    for     f   循环控制（支持步长和条件退出）                     f i=1:1:10 w i,!（输出 1 到 10）
    
    6,其他
    $i  $increment  原子递增计数器（避免并发冲突）
    ..  序列生成符   生成连续整数序列（如 s list=1..5 → [1,2,3,4,5]）6
    {}  列表索引运算符 按位置访问列表元素（如 list{2} 获取第2个元素）6
    []  记录字段访问运算符   按名称访问记录字段（如 rec["name"]）

    $p：$piece 的简写
    $s：$select 的简写
    
    【列表的常用函数】
    $listbuild(element1,element2,...) 定义列表                          set fruits = $listbuild(123, "Orange", ")
    $list(list, pos)    $lb     提取指定位置元素                        write $list(fruits, 2) → "orange"
    $listget(list, pos) $lg     安全提取元素（防越界）                  write $listget(fruits, 5) → "
    $listlength(list)   $ll     获取元素数量                            write $listlength(fruits) → 3
    $listtostring(list) $lts    转换为字符串  `                         set str = $listtostring(fruits, "  ")→"apple   orange  banana"`
    $listvalid(list)    $lv     验证是否为列表                          write $listvalid(fruits) → 1
    $listfromstring()   $lfs    将分隔符字符串转换为列表。              set list=$listfromstring("fruits") -$lb("fruits")
                                                                        zw $listfromstring("fruits,apple")    --> $lb("fruits","apple")

    【$zobjproperty 是用于对象属性操作的系统函数】
    ; 动态获取属性（属性名存储在变量中）
    s propName = "PatientID"
    s id = $zobjproperty(obj, propName)  ; 等价于 obj.PatientID
    
    s obj = "  ; 空对象
    s val = $zobjproperty(obj, "Name") ; 错误：<INVALID OREF>
    s val = $zobjproperty(obj, "Name11223") ; 错误：<PROPERTY DOES NOT EXIST>
    
    解决：
    ; 使用 $isobject() 检查对象引用
    ; 使用 $property() 检查属性是否存在
    if $isobject(set) && ($property(set, key) '= ") {
        s value = $zobjproperty(set, key)
    }
    
    函数  用途
    $zobjmethod()   动态调用对象方法
    $zobjclass()    获取对象的类名
    $isobject() 检查变量是否为有效对象
    
    // 获取当前类名
    s className = $CLASSNAME()
    w "当前类名: ", className, !

*/

/// Creator:      gaoruishan
/// CreatDate:    2025-06-18
/// Description:  工具类---不再调用复杂类，保证纯干净
/// *******************
Class Nur.Tools Extends %RegisteredObject
{

/// 将2025-06-18格式转换67374格式,默认当前日期
/// 测试1: w ##class(Nur.Tools).Date()              --->67389   
/// 测试2: w ##class(Nur.Tools).Date("")            --->67389  
/// 测试3: w ##class(Nur.Tools).Date("2025-07-03")  --->67389  
/// 测试4: w ##class(Nur.Tools).Date("67389")       --->67389  
/// 测试5: w ##class(Nur.Tools).Date("03/07/2025")  --->67389  
ClassMethod Date(val)
{
    ; $h即$HOROLOG 钟表, $zd即 $ZDATE
    q $s( $g(val)="":$p($h,",",1),  1:##class(websys.Conversions).DateHtmlToLogical(val))
}

/// 将12:00格式转换43200格式,默认当前时间
/// 测试1: w ##class(Nur.Tools).Time()            --->54711   
/// 测试2: w ##class(Nur.Tools).Time("")          --->54711  
/// 测试3: w ##class(Nur.Tools).Time("15:12")     --->54720 
/// 测试4: w ##class(Nur.Tools).Time("15:12:12")  --->54732 
/// 测试4: w ##class(Nur.Tools).Time("54732")  --->54732 
ClassMethod Time(val)
{
    q $s( $g(val)="":$p($h,",",2),  1:##class(websys.Conversions).TimeHtmlToLogical(val))
}

/// 将67389 转换2025-07-03 ,默认空
/// 测试1: w ##class(Nur.Tools).ToDate()                --->""  
/// 测试2: w ##class(Nur.Tools).ToDate("67389")         --->2025-07-03  
/// 测试3: w ##class(Nur.Tools).ToDate("2025-07-03")    --->2025-07-03 
/// 测试4: w ##class(Nur.Tools).ToDate("2025-07-03",4)  --->03/07/2025
/// 测试5: w ##class(Nur.Tools).ToDate("2025-07-03",1)  --->07/03/2025
ClassMethod ToDate(val, format = "3")
{
    ;$zd即 $ZDATE
    q $s( $g(val)="":"", 1:$zd(..Date(val),$g(format)))
}

/// 将54720 转换15:12 ,默认空
/// 测试1: w ##class(Nur.Tools).ToTime()  --->""  
/// 测试2: w ##class(Nur.Tools).ToTime("54720")  --->15:12 
/// 测试2: w ##class(Nur.Tools).ToTime("54732",1)  --->15:12:12 
/// 测试3: w ##class(Nur.Tools).ToTime("15:12")  --->2025-07-03 
ClassMethod ToTime(val, format = "2")
{
    q $s( $g(val)="":"", 1:$zt(..Time(val),$g(format)))
}

/// 将用户ID/工号/名字 转换用户ID,默认空
/// 测试1: w ##class(Nur.Tools).User()            --->""  
/// 测试2: w ##class(Nur.Tools).User("20665")     --->"20665"  
/// 测试3: w ##class(Nur.Tools).User("HS01")      --->"20665"  
/// 测试4: w ##class(Nur.Tools).User("护士01")    --->"20665" 
ClassMethod User(val)
{
    q:$g(val)="" ""
    i $d(^SSU("SSUSR",val)) q val ;返回UserId
    s value1=$o(^SSU("SSUSR",0,"SSUSR_Initials",$$ALPHAUP^SSUTIL4(val),""))
    i $g(value1)'=""  q value1 ;通过工号获取UserId
    s value2=$o(^SSU("SSUSR",0,"SSUSR_Name",$$ALPHAUP^SSUTIL4(val),""))
    i $g(value2)'=""  q value2 ;通过名字获取UserId
    q ""
}

/// 将"20665"用户ID 转换"护士01"用户名称,默认空
/// 测试1: w ##class(Nur.Tools).ToUser()           --->""  
/// 测试2: w ##class(Nur.Tools).ToUser("20665")    --->"护士01"  
/// 测试3: w ##class(Nur.Tools).ToUser("HS01")     --->"护士01"
/// 测试3: w ##class(Nur.Tools).ToUser("护士01")   --->"护士01"    
ClassMethod ToUser(val, peace = "2")
{
    q:$g(val)="" ""
    i $isobject(val) q $p($g(^SSU("SSUSR",val.%Id())),"^",peace)
    i $d(^SSU("SSUSR",val)) q $p($g(^SSU("SSUSR",val)),"^",peace) ;如果是UserId返回用户名字
    s userId=..User(val) ;获取用户id,再用户名字
    i $g(userId)'="" q $p($g(^SSU("SSUSR",userId)),"^",peace)
    q ""
}

/// 如果A不为空,则返回A; 如果B不为空，则返回B
ClassMethod ABNull(a, b)
{
    q $s($g(a)'="":a,$g(b)'="":b,1:"")
}

/// #define ABNull(%a,%b) $s(%a'="":%a,%b'="":%b,1:"")
/// ToUser(%val,%peace)
/// 从A 或B 中选择：条件c成立选A,不成立B
ClassMethod ABCS(a, b, c)
{
    q $s( c:a,  1:b)
}

/// 获取obj对象的数量，默认返回 0
/// 测试1: w ##class(Nur.Tools).Size(##class(%ArrayOfDataTypes).%New())                               --> 0
/// 测试2: s a=##class(%ArrayOfDataTypes).%New() d a.SetAt("11","key") w ##class(Nur.Tools).Size(a)   --> 1
/// 测试3: s a=##class(%ListOfDataTypes).%New() d a.Insert("key") w ##class(Nur.Tools).Size(a)        --> 1
/// 测试4: w ##class(Nur.Tools).Size(^CT.NUR.MNIS.MainModuleD(1))                                     --> 6
ClassMethod Size(obj)
{
    ; $lv()即$listvalid(list), 用于验证变量是否为列表结构，返回布尔值 1（是列表）或 0（不是列表）
    ; $ll()即$listlength(list)   获取元素数量 
    q $s(  $isobject(obj):..Count(obj),  ($lv(obj))&&(obj'=$lb()):$ll(obj),  1:0)
}

/// 获取obj对象的长度，默认返回 0
ClassMethod Length(obj, del)
{
    q $s( $g(obj)="":0,  $isobject(obj):..Count(obj),  ($lv(obj))&&(obj'=$lb()):$ll(obj),  $g(del)'="":$l(obj,del),  1:0)
}

/// 获取obj对象的数量，默认返回 0
/// 注意：obj非空对象
/// 测试1: w ##class(Nur.Tools).Count(##class(%ArrayOfDataTypes).%New())                              --> 0
/// 测试2: s a=##class(%ArrayOfDataTypes).%New() d a.SetAt("11","key") w ##class(Nur.Tools).Count(a)  --> 1
/// 测试3: s a=##class(%ListOfDataTypes).%New() d a.Insert("key") w ##class(Nur.Tools).Count(a)       --> 1
/// 测试4: w ##class(Nur.Tools).Count("status")                                                       --> 0
ClassMethod Count(obj)
{
    ; HasMeth如果有Count,就返回obj.Count()
    q $s(  ..HasMeth(obj,"Count"):obj.Count(),  ..HasMeth(obj,"Size"):obj.Size(),  ..HasProp(obj,"Size"):obj.Size,  1:0)
}

/// 是否包含key方法
/// 测试1：w ##class(Nur.Tools).HasMeth(##class(%ArrayOfDataTypes).%New(),"Count")      --> 1
/// 测试2：w ##class(Nur.Tools).HasMeth(##class(%ListOfDataTypes).%New(),"Count")       --> 1
/// 测试3：w ##class(Nur.Tools).HasMeth(##class(Nur.Tools).%New(),"Date")               --> 1
ClassMethod HasMeth(obj, key)
{
    ; $classname(obj) 返回类名称；例如：w $classname(##class(Nur.Tools).%New()) -->"Nur.Tools"
    q ($isobject(obj))&&($d(^oddCOM($classname(obj),"m",key)))
}

/// 是否包含key属性
/// 测试1：w ##class(Nur.Tools).HasProp(##class(%ArrayOfDataTypes).%New(),"Size")      --> 0
/// 测试2：w ##class(Nur.Tools).HasProp(##class(%ListOfDataTypes).%New(),"Size")       --> 1
///       查看 zw ^oddCOM("%Library.ListOfDataTypes","a","Size")
ClassMethod HasProp(obj, key)
{
    ; $classname(obj) 返回类名称；例如：w $classname(##class(%ListOfDataTypes).%New()) -->"%Library.ListOfDataTypes"
    q ($isobject(obj))&&($d(^oddCOM($classname(obj),"a",key)))
}

/// 是否有定义key
/// 示例：s obj= ##class(Nur.MNISV3.Service.Accompany).GetEscortObj(1)
///        w ##class(Nur.Tools).IsDefined(obj,"NCPAInfo1")  ---> 1
/// zw ^oddCOM("%Library.ArrayOfDataTypes","m",IsDefined") ---> 1
/// zw ^oddCOM("%Library.ArrayOfDataTypes","m","ContainsKey")  --->0
ClassMethod IsDefined(obj, key)
{
    ; zw ^oddCOM("%Library.ArrayOfDataTypes","m","IsDefined") 
    q $s(  ..HasMeth(obj,"IsDefined"):obj.IsDefined(key),  ..HasMeth(obj,"ContainsKey"):obj.ContainsKey(key),  1:0)
}

/// 从obj中取出key对应的value,默认返回“”
/// 测试1：w ##class(Nur.Tools).GetAt("","name") -->""
/// 测试2：RapidAssembly快速组装个对象 s set=##class(Nur.Tools).RapidAssembly("name,age","张三","18") 
///         w ##class(Nur.Tools).GetAt(set,"name")    --> 张三
ClassMethod GetAt(obj, key)
{
    ; zw ^oddCOM("%Library.ArrayOfDataTypes","m","GetAt") 
    q $s(  ..HasMeth(obj,"GetAt"):obj.GetAt(key),  ..HasMeth(obj,"Get"):obj.Get(key),  ..HasMeth(obj,key_"Get"):$zobjmethod(obj,key_"Get"),  1:"")
}

/// 是否是set对象: 如果是$isobject(),并包含Next()和GetAt()方法
/// 测试1：w ##class(Nur.Tools).IsSet(##class(%ListOfDataTypes).%New())     --> 1
/// 测试2：w ##class(Nur.Tools).IsSet(##class(%ArrayOfDataTypes).%New())    --> 1
ClassMethod IsSet(set) As %String [ Internal ]
{
    q ($isobject(set))&&($d(^oddCOM($classname(set),"m","Next")))&&($d(^oddCOM($classname(set),"m","GetAt")))
}

/// 是否是list对象: 如果是$isobject(),并包含Next()和GetAt()，Insert()方法
/// 测试1：w ##class(Nur.Tools).IsList(##class(%ListOfDataTypes).%New())     --> 1
/// 测试2：w ##class(Nur.Tools).IsList(##class(%ArrayOfDataTypes).%New())    --> 0
ClassMethod IsList(set) As %String [ Internal ]
{
    ; 必须先是 set对象
    q (..IsSet(set))&&($d(^oddCOM($classname(set),"m","Insert")))
}

/// 和 isList相反，不包含Insert()方法
ClassMethod IsMap(set) As %String [ Internal ]
{
    q (..IsSet(set))&&('$d(^oddCOM($classname(set),"m","Insert")))
}

/// set对象的Count()数量: 默认返回 0 
/// 测试1：s set=##class(Nur.Tools).RapidStuff("name,age",##class(%ArrayOfDataTypes).%New(),"张三","18")  
///        w ##class(Nur.Tools).CountSet(set)     --> 2
ClassMethod CountSet(set) As %String [ Internal ]
{
    /*  set=110@%Library.ArrayOfDataTypes  ; <OREF>
        +----------------- general information ---------------
        |      oref value: 110
        |      class name: %Library.ArrayOfDataTypes
        | reference count: 2
        +----------------- attribute values ------------------
        |        Data("age") = 18
        |       Data("name") = "张三"
        |        ElementType = "%String"
        +-----------------------------------------------------*/
    q $s(  ($isobject(set))&&($d(^oddCOM($classname(set),"m","Count"))):set.Count(),  1:0)
}

/// 连接(Concat)字符 如果obj空 返回key; 如果key空 返回obj; 如果obj是对象,且包含Concat,否则返回obj; 默认返回obj_del_key拼接
/// 测试1：s Content="", value="内容"
///     第一次Content是“”  s Content=##class(Nur.Tools).Concat(Content," ",value) -->内容
///     第二次Content是“内容”  s Content=##class(Nur.Tools).Concat(Content," ",value) -->内容 内容
/// 测试2：  s Content=##class(Nur.Tools).Concat("初始"," ",value) -->初始 内容
ClassMethod Concat(obj, del, key) As %String [ Internal ]
{
    q $s(  $g(obj)="":$g(key), $g(key)="":$g(obj),  $isobject($g(obj)):$s( ..HasMeth(obj,"Concat"):obj.Concat(key), 1:obj), 1:$g(obj)_$g(del)_$g(key))
}

/// 是否存在 类的方法
/// 测试：w ##class(Nur.Tools).ExistClass("Nur.Tools")    -->1
/// 测试：w ##class(Nur.Tools).ExistClass("Nur.Tools1")   -->0
ClassMethod ExistClass(className)
{
    ;..%Exists($listbuild(id)) 先转 zw $listbuild("Nur.Tools") ---- 调用.%Open()
    ; w ##class(%Dictionary.ClassDefinition).%Open($listbuild("Nur.Tools"),0) -->143@%Dictionary.ClassDefinition
    q ##class(%Dictionary.ClassDefinition).%ExistsId(className)
}

/// 是否存在 类的方法
/// 测试：w ##class(Nur.Tools).ExistMedhod("Nur.Tools","TEST1")   -->0
/// 测试：w ##class(Nur.Tools).ExistMedhod("Nur.MNIS.Service.WebService","RequestData")   -->1
ClassMethod ExistMedhod(className, method)
{
    ;..%Exists($listbuild(id)) 先转 zw $listbuild("Nur.Tools||Concat") ---- Set classname = $$$oidClassName(oid)
    ; #define oidClassName(%oid)                $listget(%oid,2)
    q ##class(%Dictionary.MethodDefinition).%ExistsId(className_"||"_method)
}

/// 某个类方法，是否存在 参数
/// 测试：w ##class(Nur.Tools).ExistMedhodParam("Nur.Tools","ExistMedhodParam","method1")   -->0
/// 测试：w ##class(Nur.Tools).ExistMedhodParam("Nur.Tools","ExistMedhodParam","method")    -->1
ClassMethod ExistMedhodParam(className, method, param = "")
{
    q:param="" 0
    s params=..GetMethodParam(className,method)
    s params="^"_params_"^" ;前后加^
    q params[("^"_param_"^")
}

/// 获取类方法入参串
/// 测试：w ##class(Nur.Tools).GetMethodParam("Nur.Tools","GetMethodParam")   -->className^method
ClassMethod GetMethodParam(className As %String, method) As %String
{
    s mParam=$g(^oddCOM(className,"m",method,60))
    q:mParam="" ""
    s num=$ll(mParam) , param=""
    f n=1:1:num d
    .s parameter=$li(mParam,n)
    .s name=$li(parameter,1)
    .s param= $s(param="":name,1:param_"^"_name)
    q param
}

/// 将resultSet组装到obj对象中,并返回
ClassMethod ResultSet(resultSet As %ResultSet) As %ArrayOfDataTypes
{
    s Obj=##class(%ArrayOfDataTypes).%New()
    i '$IsObject(resultSet) q Obj
    f len=1:1:resultSet.GetColumnCount()
    {
         s ColumnName=resultSet.GetColumnName(len) 
         s Value=resultSet.GetDataByName(ColumnName)
         d Obj.SetAt(Value,ColumnName)
    }
    q Obj
}

/// 将resultSet组装到List对象中,并返回
ClassMethod ResultSetToList(resultSet As %ResultSet) As %ListOfDataTypes
{
    s List=##class(%ListOfDataTypes).%New()
    i '$IsObject(resultSet) q List
    while (resultSet.Next()){
        s obj= ..ResultSet(resultSet)
        d List.Insert(obj)
    }
    q List
}

/// ----------------------------------------------组合-------------------------------------------------------
/// 将set添加(Append)到list中
/// 说明：AppendSet: 将第二个obj添加到list中,第一个参数可以空  或%ListOfDataTypes对象
/// 测试1：w ##class(Nur.Tools).AppendSet(,"618")                                   --> ["618"]
///      相同效果 w ##class(Nur.Tools).AppendSet(##class(%ListOfDataTypes).%New(),"618")
/// 测试2：w ##class(Nur.Tools).AppendSet(,##class(%ArrayOfDataTypes).%New())       --> [{}]
/// 测试3：w ##class(Nur.Tools).AppendSet(##class(%ListOfDataTypes).%New(),)        --> [[]]
ClassMethod AppendSet(list, set) As %String [ Internal ]
{
    i ($d(list))&&('$d(set)) s set=list,list="" ;测试3 这种情况
    i ($g(list)="") s list=##class(%ListOfDataTypes).%New() ;空 创建一个list对象
    d list.Insert(set)
    q list
}

/// 快速(Rapid)组装(Assembly)一个{}。大约只会在业务层使用。最多254个参数
/// 说明：RapidAssembly: Rapid快速 Assembly组装成一个obj, 第一个参数“,”分割 和后面顺序对应
/// 测试: s a=##class(Nur.Tools).RapidAssembly("name,age","张三","18") 
///       w ##class(Nur.JSON).Encode(a) -->{"age":18,"name":"张三"}
ClassMethod RapidAssembly(keys, args...) As %String [ Internal ]
{
    ; 调用RapidStuff 第二参数 创建一个对象
    q ..RapidStuff(keys,##class(%ArrayOfDataTypes).%New(),args...)
}

/// 快速(Rapid)装填(Stuff)一个对象， 第一个参数“,”分割 和后面args顺序对应
/// 测试: s a=##class(Nur.Tools).RapidStuff("name,age",##class(%ArrayOfDataTypes).%New(),"张三","18") 
///       w ##class(Nur.JSON).Encode(a) -->{"age":18,"name":"张三"}
ClassMethod RapidStuff(keys, obj, args...) As %String [ Internal ]
{
    q:('$isobject(obj)) obj ;不是对象,直接返回
    s ks=$replace(keys,"^",",") ;替换,分割符
    ; w $lfs("name,age",",") -->转换成 $lb("name","age")  语法：$listfromstring() 将分隔符字符串转换为列表
    ; w $ll(lb) --> 长度 2
    s lb=$lfs(ks,","),ll=$ll(lb)
    f i=1:1:ll {
        s key=$lg(lb,i)  ;w $lg(lb,i) -->依次取出 name  age
        continue:(key="")
        ; 这种格式: args=2 
        ;    args(1)="张三"
        ;    args(2)=18
        s value=$g(args(i)) 
        d obj.SetAt(value,key)
    }
    q obj
}

/// 快速(Rapid)获取属性(Prop)，从set对象中取出key属性的数据,存到obj对象中
/// 测试：创建对象     s set=##class(Nur.Tools).RapidStuff("name,age",##class(%ArrayOfDataTypes).%New(),"张三","18") 
///       获取新对象   s obj2=##class(Nur.Tools).RapidProp("name",set)  w ##class(Nur.JSON).Encode(obj2) -->{"age":18,"name":"张三"}
ClassMethod RapidProp(keys, set) As %ArrayOfDataTypes [ Internal ]
{
    s obj=##class(%ArrayOfDataTypes).%New()
    s ks=$replace(keys,"^",",")   ;替换,分割符
    s lb=$lfs(ks,","),ll=$ll(lb)  ;转换成列表$lb("name","age") 并获取长度$ll 语法：$listfromstring() 将分隔符字符串转换为列表
    f i=1:1:ll {
        s key=$lg(lb,i)
        continue:(key="")
        ; 动态获取obj属性（属性名存储在变量key中）
        ; s propName = "PatientID"
        ; s id = $zobjproperty(obj, propName) // 等价于 obj.PatientID
        try {
            s value=$zobjproperty(set,key)
            ;特殊处理：Data("%%OID") = $lb("100","CF.NUR.SHIFT.ShiftBook")
            i key="%%OID" d obj.SetAt($lg(value,1),"ID")
            e  d obj.SetAt(value,key)
       } catch ex {
            d obj.SetAt("",key)
       }
    }
    q obj
}

/// 合并两个对象：如果1:是List则Insert插入; 如果2:是Set则SetAt合并; 
/// 测试1：s set1=##class(Nur.Tools).RapidStuff("name1,age1",##class(%ArrayOfDataTypes).%New(),"张三1","11")  
///        s set2=##class(Nur.Tools).RapidStuff("name2,age2",##class(%ArrayOfDataTypes).%New(),"张三2","22") 
///        w ##class(Nur.JSON).Encode(##class(Nur.Tools).Merge(set1,set2)) --->{"age1":11,"age2":22,"name1":"张三1","name2":"张三2"}   
ClassMethod Merge(ByRef obj, ByRef set)
{
    i (..IsSet(set)) { ;第二个参数set对象-要有Next和GetAt方法
        i (..IsList(obj)) { ;如果是List,进行obj.Insert(value)
            s key=set.Next("")
            while (key'="") {
                s value=set.GetAt(key)
                d obj.Insert(value)
                s key=set.Next(key)
            }
        } else {  ;如果是Set,进行obj.SetAt(value,key)
            s key=set.Next("")
            while (key'="") {
                s value=set.GetAt(key)
                d obj.SetAt(value,key)
                s key=set.Next(key)
            }
        }
    }
    q obj
}

/// 合并两个对象,和Merge相同
ClassMethod MergeSet(ByRef obj, ByRef set)
{
    q ..Merge(obj,set)
}

/// 合并两个List
ClassMethod ListJoin(List1 As %ListOfDataTypes, List2 As %ListOfDataTypes) As %ListOfDataTypes
{
    Set key=""
    For {
        Set item=List2.GetNext(.key)        
        Quit:key=""
        Do List1.Insert(item)
    }
    Quit List1
}

/// 合并两个Array
ClassMethod ArrayJoin(Array1 As %ArrayOfDataTypes, Array2 As %ArrayOfDataTypes) As %ArrayOfDataTypes
{
    s key=Array2.Next("")
    while(key'="")
    {
        s value=Array2.GetAt(key)
        d Array1.SetAt(value,key)
        s key=Array2.Next(key)
    }
    q Array1
}

/// 对应PC的配置：CT.NUR.NIS.NurseBasicData
/// 数据类型 NBDType  患者信息:0 ,医嘱信息:1 ,执行记录信息:2 ,打印信息:3 ,护理计划:4 ,分娩信息:5
/// 索引：^CT.NUR.NIS.NurseBasicDataI("Code"," NBDType"," NBDCode")
/// w ##class(Nur.Tools).GetBasicFieldValue("execDateTime","1271||27")
ClassMethod GetBasicFieldValue(key, oeoreId) As %String
{
    i (key="ID") {
        s value=oeoreId
    } else {
        s ll=$l(oeoreId,"||")
        i (ll=3) { ; type=2 执行记录信息
            s id=$o(^CT.NUR.NIS.NurseBasicDataI("Code"," 2"," "_$zcvt(key,"U"),""))
        } 
        ; type=1 医嘱信息
        i $g(id)=""  s id=$o(^CT.NUR.NIS.NurseBasicDataI("Code"," 1"," "_$zcvt(key,"U"),""))
        q:$g(id)="" ""
        s type=$lg($g(^CT.NUR.NIS.NurseBasicDataD(id)),3)
        w id_"-"_type,"-",key,"-",oeoreId,!
        s value=..GetBasicDataByCode(type,key,oeoreId)
    }
    q $g(value)
}

/// 通过code获取基础数据值
/// 基础数据表code,就诊号,医嘱id,执行记录id
/// w ##class(Nur.NIS.Service.Base.BedConfig).GetBasicDataByCode()
ClassMethod GetBasicDataByCode(type, code, parameter = "") As %String
{
    q:code="" ""
    s code=$zcvt(code,"U")
    s rowId=$o(^CT.NUR.NIS.NurseBasicDataI("Code"," "_type," "_code,""))
    q:rowId="" ""
    s basicData=$g(^CT.NUR.NIS.NurseBasicDataD(rowId))
    s callMethod=$lg(basicData,6)
    s className=$p(callMethod,":",1)
    s methodName=$p(callMethod,":",2)
    i (className'="")&&(methodName'="") {
        q:'##class(websys.Conversions).IsValidMethodName(className,methodName) ""
        s x="(i,o) s o=##class("_className_")."_methodName_"("""_parameter_""")"
        x (x,"",.ret)
    }else{
        q ""
    }
    q ret
}

/// 快速(Rapid)解压(Extract)。可以传入引用(并对引用赋值)，也可以使用生成的{}型
/// 测试1：s extras=##class(Nur.JSON).Decode("{""single"":""1"",""screening"":""2"",""book"":""3"",""multiple"":""1"",""class"":""4""}")
///        s obj=##class(Nur.Tools).RapidExtract("book,class,time,screening",extras,.selectedBookId,.selectedClassId,.selectedTimeId,.selectedScreeningId)
///        即可对引用赋值：w selectedBookId 对应book的值-->3  w selectedClassId 对应class的值-->4  w selectedTimeId 对应time的值-->""
///        w ##class(Nur.JSON).Encode(obj)   -->{"book":"3","class":"4","screening":"2","time":""}
/// 测试2：如果是空 s extras="" 或 ##class(%ArrayOfDataTypes).%New()
///        s obj=##class(Nur.Tools).RapidExtract("book,class,time,screening",extras,.selectedBookId,.selectedClassId,.selectedTimeId,.selectedScreeningId)
///        w ##class(Nur.JSON).Encode(obj)   -->{"book":"","class":"","screening":"","time":""}
ClassMethod RapidExtract(keys As %String, json, args...) As %ArrayOfDataTypes [ Internal ]
{
    s obj=##class(%ArrayOfDataTypes).%New()
    s ks=$replace(keys,"^",",")
    ;转换成列表$lb("name","age") 并获取长度$ll 语法：$listfromstring() 将分隔符字符串转换为列表
    s lb=$lfs(ks,","),len=$ll(lb) ;获取长度
    f i=1:1:len {
        s key=$lg(lb,i)
        continue:(key="")
        s value=..GetAt(json,key) ;调用GetAt获取数据，默认“”
        d obj.SetAt(value,key)
        s args(i)=value  ;对传递引用 赋值
    }
    q obj
}

/// 快速(Rapid)抽取子集(Subset)，和上面RapidExtract很类似
/// 测试1：s extras=##class(Nur.JSON).Decode("{""single"":""1"",""screening"":""2"",""book"":""3"",""multiple"":""1"",""class"":""4""}")
///        s obj=##class(Nur.Tools).RapidSubset("book,class,time,screening",extras)
///        w ##class(Nur.JSON).Encode(obj)   -->{"book":"3","class":"4","screening":"2","time":""}
ClassMethod RapidSubset(keys As %String, set) As %ArrayOfDataTypes [ Internal ]
{
    s obj=##class(%ArrayOfDataTypes).%New()
    s ks=$replace(keys,"^",",")
    ;转换成列表$lb("name","age") 并获取长度$ll 语法：$listfromstring() 将分隔符字符串转换为列表
    s lb=$lfs(ks,","),len=$ll(lb)
    f i=1:1:len {
        s key=$lg(lb,i)
        continue:(key="")
        s value=..GetAt(set,key) ;调用GetAt获取数据，默认“”
        d obj.SetAt(value,key)
    }
    q obj
}

/// 内部(Inner)抽取子集(Subset)：只获取keys定义的数据,原来的list已经改变
/// 测试1：s list=##class(%ListOfDataTypes).%New() 
///        d list.Insert(##class(Nur.JSON).Decode("{""book"":""3"",""class"":""4""}"))
///        d list.Insert(##class(Nur.JSON).Decode("{""screening"":""2"",""class"":""4""}"))
///        s obj=##class(Nur.Tools).InnerSubset(list,"book,class,time,screening")
///        w ##class(Nur.JSON).Encode(obj)   -->[{"book":3,"class":4,"screening":"","time":""},{"book":"","class":4,"screening":2,"time":""}]
ClassMethod InnerSubset(list As %ListOfDataTypes, keys As %String) As %ListOfDataTypes [ Internal ]
{
    s len=list.Count()
    i (len>0) {
        f i=1:1:len {
            s set=list.GetAt(i)
            ; 快速(Rapid)抽取子集(Subset)，返回一个obj对象
            s obj=..RapidSubset(keys,set)
            d list.SetAt(obj,i) ;重新赋值 同insert
        }
    }
    q list
}

/// 快速(Rapid)减轻(Lessen),只保留Set对象中的keys
/// 测试1：s extras=##class(Nur.JSON).Decode("{""single"":""1"",""screening"":""2"",""book"":""3"",""multiple"":""1"",""class"":""4""}")
///        s obj=##class(Nur.Tools).RapidLessen("book,class",extras)
///        w ##class(Nur.JSON).Encode(obj)   -->只剩下 {"book":3,"class":4}
ClassMethod RapidLessen(keys As %String, set) As %String [ Internal ]
{
    k tmp
    s ks=$replace(keys,"^",",")
    ;转换成列表 $lb("name","age") 并获取长度$ll 语法：$listfromstring() 将分隔符字符串转换为列表
    s lb=$lfs(ks,","),len=$ll(lb)
    f i=1:1:len {
        s key=$lg(lb,i)
        continue:(key="")
        s tmp(key)=""
    }
    s key=set.Next("")
    while (key'="") {
        i ('$d(tmp(key))) { ; 不包含的key, 移除
            d set.RemoveAt(key)
        }
        s key=set.Next(key)
    }
    q set
}

/// 将字符串分割成list对象 (delimiter:分隔符) 
/// 测试1：w ##class(Nur.JSON).Encode(##class(Nur.Tools).GetOptionsAsList("观察30分钟复测"_$c(13)_"呼叫管床医生",$c(13))) -->["观察30分钟复测","呼叫管床医生"]
/// 测试2：w ##class(Nur.JSON).Encode(##class(Nur.Tools).GetOptionsAsList("[观察30分钟复测"_$c(13)_"呼叫管床医生]",$c(13))) -->["观察30分钟复测","呼叫管床医生"]
/// 测试3：w ##class(Nur.JSON).Encode(##class(Nur.Tools).GetOptionsAsList("姓名,登记号",",")) -->["姓名","登记号"]
ClassMethod GetOptionsAsList(options As %String, delimiter) As %String
{
    ;如果包含[],先去掉
    i ($e(options,1)="[")&&($e(options,*)="]") s options=$e(options,2,*-1)
    i ($g(delimiter)="") s delimiter=$c(129)
    s items=##class(%ListOfDataTypes).%New()
    s len=..Length(options,delimiter)
    f ind=1:1:len {
        s item=$p(options,delimiter,ind)
        d items.Insert(item)
    }
    q items
}

/// 快速映射keys (Mapping:映射)
/// 测试1： s item=##class(Nur.JSON).Decode("{""VSId"":""1"",""VSCode"":""CS"",""VSDesc"":""测试""}")
///         s obj=##class(Nur.Tools).RapidMapping("VSId,VSCode,VSDesc",item,"rowid","code","desc" )
///         w ##class(Nur.JSON).Encode(obj)    -->对应keys顺序映射 {"code":"CS","desc":"测试","rowid":1}
ClassMethod RapidMapping(keys, set, args...) As %String [ Internal ]
{
    s obj=##class(%ArrayOfDataTypes).%New()
    s ks=$replace(keys,"^",",")
    ;转换成列表 $lb("name","age") 并获取长度$ll 语法：$listfromstring() 将分隔符字符串转换为列表
    s lb=$lfs(ks,","),ll=$ll(lb)
    f li=1:1:ll {
        s key=$lg(lb,li)
        continue:(key="")
        s value=set.GetAt(key)
        s name=$g(args(li))
        i (name="") s name=key
        d obj.SetAt(value,name)
    }
    q obj
}

/// 将list映射到temp变量上,取指定key和对应value
/// 测试1： s list=##class(%ListOfDataTypes).%New() 
///         d list.Insert(##class(Nur.JSON).Decode("{""text"":""未执行"",""value"":""0""}"))
///         d list.Insert(##class(Nur.JSON).Decode("{""text"":""已执行"",""value"":""1""}"))
///         w ##class(Nur.Tools).InnerMappingTemp(.tmp,list,"value","text") -->固定1, 但zw tmp  tmp(0)="未执行" tmp(0)="未执行"
ClassMethod InnerMappingTemp(ByRef temp, list, key, value) As %String [ Internal ]
{
    k temp
    s len=list.Count()
    f ind=1:1:len {
        s item=list.GetAt(ind)
        s val1=item.GetAt(key)
        continue:(val1="")
        s val2=item.GetAt(value)
        s temp(val1)=val2
    }
    q $$$OK
}

ClassMethod EvalExpr(expr, value) As %String
{
    s l1=$e(expr,1)
    s l2=$e(expr,1,2)
    s r1=$e(expr,2,*)
    s r2=$e(expr,3,*)
    i (l2="<=") s result=value'>r2
    e  i (l2=">=") s result=value'<r2
    e  i (l2="==") s result=value=r2
    e  i (l1="<") s result=value<r1
    e  i (l1=">") s result=value>r1
    e  i (l1="=") s result=value=r1
    e  s result=value=expr
    q result
}

/// 快速替换keys
ClassMethod RapidRekey(keys, obj, args...) As %String [ Internal ]
{
    s ks=$replace(keys,"^",",")
    s lb=$lfs(ks,","),ll=$ll(lb)
    f li=1:1:ll {
        s key=$lg(lb,li)
        continue:(key="")
        s value=obj.GetAt(key)
        s name=$g(args(li))
        continue:(name="")||(name=key)
        d obj.RemoveAt(key)
        d obj.SetAt(value,name)
    }
    q obj
}

/// 一层层取数据，最右侧
/// 测试1： w ##class(Nur.Tools).Ununit("000.11（222(333")  --> 000
/// 测试2： w ##class(Nur.Tools).Ununit("11（222(333")      --> 11
/// 测试3： w ##class(Nur.Tools).Ununit("222(333")         --> 222
ClassMethod Ununit(str) As %String
{
    q $p($p($p(str,"("),"（"),".")
}

/// 将CS|测试^CD|码 格式字符串存temp
/// 测试1： w ##class(Nur.Tools).ExtractFilterStr("tStatus|已执行!",.temp) -->temp("tStatus")="已执行!"
ClassMethod ExtractFilterStr(screenParts, ByRef temp) As %String
{
    s len=$l(screenParts,"^")
    f i=1:1:len {
        s part=$p(screenParts,"^",i)
        s name=$p(part,"|")
        continue:(name="")
        s value=$p(part,"|",2)
        s temp(name)=value
    }
    q $$$OK
}

/// 获取当前对象%ArrayOfDataTypes
/// s val=##class(Nur.Tools).GetVal(##class(CF.NUR.MNISV3.ModelForm).%OpenId(1))
/// w ##class(Nur.JSON).Encode(val) 
ClassMethod GetVal(data As %Persistent) As %ArrayOfDataTypes
{
    s ret=""
    s $zt="errGetVal"
    s obj=##class(%ArrayOfDataTypes).%New()
    s className=data.%ClassName(1) ; 1是获取全类名
    //s className = $CLASSNAME() ;获取当前类名
    //s a=..%OpenId(id) ;打开当前对象
    s tdata="",tmp=""
    s p="" 
    f  
    {
        s p=$O(^oddCOM(className,"a",p))
        q:p="" 
        continue:p["%"
        s typ=^oddCOM(className,"a",p,40)
        s tmp(p)=$ZOBJPROPERTY(data,p)
        //处理日期 时间
        i (typ="%Library.Date")&&(tmp(p)'="") s tmp(p)=$ZD(tmp(p),3)
        i (typ="%Library.Time")&&(tmp(p)'="") s tmp(p)=$ZT(tmp(p))
        //处理用户Id-->姓名
        i (p["User")&&(tmp(p)'="") { 
            i $d(^SSU("SSUSR",tmp(p))) s tmp(p)=$P($G(^SSU("SSUSR",tmp(p))),"^",2)
        }
        d obj.SetAt(tmp(p),p)
    }
    q obj
errGetVal
  w $ze,!
  q
}

/// =====================将简单字符串{}或[],转换成对象===========================
/// 测试1：数组转换示例
/// zw ##class(Nur.Tools).ConvertToCollection("[""apple"", ""banana"", ""cherry""]")
/// 测试2：对象转换示例
/// set array = ##class(Nur.Tools).ConvertToCollection("{""name"":""John"", ""age"":30, ""city"":""NY""}")
ClassMethod ConvertToCollection(str)
{
    ; 去除字符串两端空格
    set str = $zstrip(str, "<>W")
    if str = "" return ""
    if $extract(str, 1) = "[" { ; [开头 %ListOfDataTypes (数组)
        set list = ##class(%ListOfDataTypes).%New()
        ; 移除方括号并分割元素
        set cleanStr = $replace($extract(str, 2, *-1), """", "") ; 例如： apple, banana, cherry
        set elements = $listfromstring(cleanStr, ",")  ;  例如：$lb("apple"," banana"," cherry")
        ; 添加元素到列表
        for i=1:1:$listlength(elements) {
            set element = $zstrip($listget(elements, i), "<>W")
            do list.Insert(element)
        }
        return list
    }elseif $extract(str, 1) = "{" {  ; {开头 %ArrayOfDataTypes (对象)
        set array = ##class(%ArrayOfDataTypes).%New()
        ; 移除花括号并分割键值对
        set cleanStr = $replace($extract(str, 2, *-1), """", "")
        set pairs = $listfromstring(cleanStr, ",")
        ; 处理每个键值对
        for i=1:1:$listlength(pairs) {
            set pair = $zstrip($listget(pairs, i), "<>W")
            set key = $piece(pair, ":", 1)
            set value = $piece(pair, ":", 2, *)
            ; 添加到数组对象
            do array.SetAt(value, key)
        }
        return array
    } else {
        return "" ; 无效格式返回空
    }
}

// 输出: [1,["a","b"]]

/// =====================将简单对象,转换成字符串{}或[]===========================
/// 类型处理：
///     字符串：自动添加双引号并转义特殊字符
///     数字：直接输出（不加引号）
///     布尔值：直接输出 1 (true) 或 0 (false)
///     空值：输出 ""
/// 测试1： 嵌套列表示例
/// set innerList = ##class(%ListOfDataTypes).%New()
/// do innerList.Insert("a")
/// do innerList.Insert("b")
/// set outerList = ##class(%ListOfDataTypes).%New()
/// do outerList.Insert(1)
/// do outerList.Insert(innerList)
/// w ##class(Nur.Tools).ConvertToJSON(outerList)  输出: [1,["a","b"]]
/// 测试2：嵌套对象
/// set person = ##class(%ArrayOfDataTypes).%New()
/// do person.SetAt("John", "name")
/// do person.SetAt(30, "age")
/// set address = ##class(%ArrayOfDataTypes).%New()
/// do address.SetAt("123 Main St", "street")
/// do address.SetAt("New York", "city")
/// do person.SetAt(address, "address")
/// set hobbies = ##class(%ListOfDataTypes).%New()
/// do hobbies.Insert("reading")
/// do hobbies.Insert("swimming")
/// do person.SetAt(hobbies, "hobbies")
/// w ##class(Nur.Tools).ConvertToJSON(person) 输出: {"address":{"city":New York,"street":123 Main St},"age":30,"hobbies":[reading,swimming],"name":John}
/// 测试2：特殊字符转义：
/// set array = ##class(%ArrayOfDataTypes).%New()
/// do array.SetAt("Line1\nLine2", "text")
/// do array.SetAt("He said: ""Hello""", "quote")
/// w ##class(Nur.Tools).ConvertToJSON(array)  输出: {"quote":"He said: \"Hello\"","text":"Line1\\nLine2"}
ClassMethod ConvertToJSON(collection)
{
    if $isobject(collection) {
        ; 处理列表类型（数组）
        if collection.%IsA("%ListOfDataTypes") {
            return ..ListToJSON(collection)
        }
        ; 处理数组类型（对象）
        elseif collection.%IsA("%ArrayOfDataTypes") {
            return ..ArrayToJSON(collection)
        }
    }
    ; 非集合对象返回空对象
    return "{}"
}

ClassMethod ListToJSON(list)
{
    set json = "["
    set size = list.Count()
    for i = 1:1:size {
        set value = list.GetAt(i)
        ; 递归处理嵌套集合
        if $isobject(value) {
            set json = json_..ConvertToJSON(value)
        }
        ; 处理字符串类型（需要转义）
        elseif $match(value, "[a-zA-Z]") || (value = "") {
            set json = json_""""_..EscapeString(value)_""""
        }
        ; 处理数字和布尔值
        else {
            ; 直接输出原始值（不添加引号）
            ;set json = json_value
            set json = json_""""_..EscapeString(value)_"""" ;强制都转字符串
        }
        ; 添加逗号分隔符（最后一个元素不加）
        if i < size {
            set json = json_","
        }
    }
    set json = json_"]"
    return json
}

ClassMethod ArrayToJSON(array)
{
    set json = "{"
    set key = array.Next("")
    set count = 0
    while key '= "" {
        set count = count + 1
        set value = array.GetAt(key)
        ; 键名始终需要转义
        set json = json_""""_..EscapeString(key)_""":"
        ; 递归处理嵌套集合
        if $isobject(value) {
            set json = json_..ConvertToJSON(value)
        }
        ; 处理字符串类型
        elseif $match(value, "[a-zA-Z]") || (value = "") {
            set json = json_""""_..EscapeString(value)_""""
        }
        ; 处理数字和布尔值
        else {
            ; 直接输出原始值（不添加引号）
            ;set json = json_value
            set json = json_""""_..EscapeString(value)_""""  ;强制都转字符串
        }
        ; 添加逗号分隔符
        set nextKey = array.Next(key)
        if nextKey '= "" {
            set json = json_","
        }
        set key = nextKey
    }
    set json = json_"}"
    return json
}

/// 转义特殊字符
ClassMethod EscapeString(str)
{
    set str = $replace(str, "\", "\\")
    set str = $replace(str, """", "\""")
    set str = $replace(str, $char(8), "\b")   ; 退格
    set str = $replace(str, $char(12), "\f")  ; 换页
    set str = $replace(str, $char(10), "\n")  ; 换行
    set str = $replace(str, $char(13), "\r")  ; 回车
    set str = $replace(str, $char(9), "\t")   ; 制表符
    return str
}

/// ===================== 检查类 "class" 的类方法 "method" 是否有参数 "param"===========================
/// 检查类 "Nur.PDA.WebService" 的类方法 "Logon" 是否有参数 "Name"
/// Set hasParam = ##class(Nur.Tools).MethodHaveParameter("Nur.PDA.WebService", "Logon", "userCode")
/// Write hasParam  // 输出 1（存在）或 0（不存在）
ClassMethod MethodHaveParameter(className As %String, methodName As %String, paramName As %String) As %Boolean
{
    ; 1. 检查类是否存在
    If '$$$defClassDefined(className) Quit 0
    ; 2. 获取类定义
    Set classDef = ##class(%Dictionary.ClassDefinition).%OpenId(className)
    If '$IsObject(classDef) Quit 0
    ; 3. 遍历方法，找到目标方法
    Set key = ""
    For {
        Set methodDef = classDef.Methods.GetNext(.key)
        If (key = "") Quit
        Continue:(methodDef.Name '= methodName)||(methodDef.ClassMethod '= 1)  ; 检查是否为类方法
        ; 4. 解析方法的参数列表
        Set formalSpec = methodDef.FormalSpec
        Return ..ParseFormalSpec(formalSpec, paramName)
    }
    Quit 0  ; 方法不存在
}

ClassMethod ParseFormalSpec(formalSpec As %String, targetParam As %String) As %Boolean
{
    ; 空签名直接返回
    If (formalSpec = "") Quit 0
    ; 按逗号分割参数
    For i=1:1:$Length(formalSpec, ",") {
        Set param = $Piece(formalSpec, ",", i)
        ; 提取参数名（忽略 ByRef、类型和默认值）
        Set paramName = $Piece($Piece(param, ":", 1), "=", 1)  ; 去掉默认值部分
        Set paramName = $Piece($ZStrip(paramName, "<>W"), " ", *)  ; 取最后一个单词（参数名）
        ; 检查是否匹配目标参数
        If ($ZConvert(paramName, "L")=$ZConvert(targetParam, "L")) {
            return 1    ; 不区分大小写
        }
    }
    Quit 0
}

}
